/*
 * Funções para imprimir o bytecode na tela.
 */

#include "bytecode.h"

void four_bytes(unsigned int *i, char *mnemonico, unsigned char *bytecode);
void two_bytes(unsigned int *i, char *mnemonico, unsigned char *bytecode);
void one_byte(unsigned int *i, char *mnemonico, unsigned char *bytecode);

/* Funcao que escreve os mnemonicos de acordo com seu codigo em hexadecimal */
void bytecode_printer(unsigned char *bytecode, unsigned int bytecode_length) {
	unsigned int i = 0;
	unsigned char aux;

	for (i = 0; i < bytecode_length; i++) {
		aux = bytecode[i];
		switch (aux) {

		case 0x00:
			printf("\n\t\t\t\t\t%d:\t nop", i);
			break;

		case 0x01:
			printf("\n\t\t\t\t\t%d:\t aconst_null", i);
			break;

		case 0x02:
			printf("\n\t\t\t\t\t%d:\t iconst_m1", i);
			break;

		case 0x03:
			printf("\n\t\t\t\t\t%d:\t iconst_0", i);
			break;

		case 0x04:
			printf("\n\t\t\t\t\t%d:\t iconst_1", i);
			break;

		case 0x05:
			printf("\n\t\t\t\t\t%d:\t iconst_2", i);
			break;

		case 0x06:
			printf("\n\t\t\t\t\t%d:\t iconst_3", i);
			break;

		case 0x07:
			printf("\n\t\t\t\t\t%d:\t iconst_4", i);
			break;

		case 0x08:
			printf("\n\t\t\t\t\t%d:\t iconst_5", i);
			break;

		case 0x09:
			printf("\n\t\t\t\t\t%d:\t lconst_0", i);
			break;

		case 0x0a:
			printf("\n\t\t\t\t\t%d:\t lconst_1", i);
			break;

		case 0x0b:
			printf("\n\t\t\t\t\t%d:\t fconst_0", i);
			break;

		case 0x0c:
			printf("\n\t\t\t\t\t%d:\t fconst_1", i);
			break;

		case 0x0d:
			printf("\n\t\t\t\t\t%d:\t fconst_2", i);
			break;

		case 0x0e:
			printf("\n\t\t\t\t\t%d:\t dconst_0", i);
			break;

		case 0x0f:
			printf("\n\t\t\t\t\t%d:\t dconst_1", i);
			break;

		case 0x10:
			one_byte(&i, "\n\t\t\t\t\t%d:\t bipush\t\t", bytecode);
			break;

		case 0x11:
			two_bytes(&i, "\n\t\t\t\t\t%d:\t sipush\t", bytecode);
			break;

		case 0x12:
			one_byte(&i, "\n\t\t\t\t\t%d:\t ldc\t\t", bytecode);
			break;

		case 0x13:
			two_bytes(&i, "\n\t\t\t\t\t%d:\t ldc_w\t\t", bytecode);
			break;

		case 0x14:
			two_bytes(&i, "\n\t\t\t\t\t%d:\t ldc2_w\t\t", bytecode);
			break;

		case 0x15:
			one_byte(&i, "\n\t\t\t\t\t%d:\t iload\t\t", bytecode);
			break;

		case 0x16:
			one_byte(&i, "\n\t\t\t\t\t%d:\t lload\t\t", bytecode);
			break;

		case 0x17:
			one_byte(&i, "\n\t\t\t\t\t%d:\t fload\t\t", bytecode);
			break;

		case 0x18:
			one_byte(&i, "\n\t\t\t\t\t%d:\t dload\t\t", bytecode);
			break;

		case 0x19:
			one_byte(&i, "\n\t\t\t\t\t%d:\t aload\t\t", bytecode);
			break;

		case 0x1a:
			printf("\n\t\t\t\t\t%d:\t iload_0", i);
			break;

		case 0x1b:
			printf("\n\t\t\t\t\t%d:\t iload_1", i);
			break;

		case 0x1c:
			printf("\n\t\t\t\t\t%d:\t iload_2", i);
			break;

		case 0x1d:
			printf("\n\t\t\t\t\t%d:\t iload_3", i);
			break;

		case 0x1e:
			printf("\n\t\t\t\t\t%d:\t lload_0", i);
			break;

		case 0x1f:
			printf("\n\t\t\t\t\t%d:\t lload_1", i);
			break;

		case 0x20:
			printf("\n\t\t\t\t\t%d:\t lload_2", i);
			break;

		case 0x21:
			printf("\n\t\t\t\t\t%d:\t lload_3", i);
			break;

		case 0x22:
			printf("\n\t\t\t\t\t%d:\t fload_0", i);
			break;

		case 0x23:
			printf("\n\t\t\t\t\t%d:\t fload_1", i);
			break;

		case 0x24:
			printf("\n\t\t\t\t\t%d:\t fload_2", i);
			break;

		case 0x25:
			printf("\n\t\t\t\t\t%d:\t fload_3", i);
			break;

		case 0x26:
			printf("\n\t\t\t\t\t%d:\t dload_0", i);
			break;

		case 0x27:
			printf("\n\t\t\t\t\t%d:\t dload_1", i);
			break;

		case 0x28:
			printf("\n\t\t\t\t\t%d:\t dload_2", i);
			break;

		case 0x29:
			printf("\n\t\t\t\t\t%d:\t dload_3", i);
			break;

		case 0x2a:
			printf("\n\t\t\t\t\t%d:\t aload_0", i);
			break;

		case 0x2b:
			printf("\n\t\t\t\t\t%d:\t aload_1", i);
			break;

		case 0x2c:
			printf("\n\t\t\t\t\t%d:\t aload_2", i);
			break;

		case 0x2d:
			printf("\n\t\t\t\t\t%d:\t aload_3", i);
			break;

		case 0x2e:
			printf("\n\t\t\t\t\t%d:\t iaload", i);
			break;

		case 0x2f:
			printf("\n\t\t\t\t\t%d:\t laload", i);
			break;

		case 0x30:
			printf("\n\t\t\t\t\t%d:\t faload", i);
			break;

		case 0x31:
			printf("\n\t\t\t\t\t%d:\t daload", i);
			break;

		case 0x32:
			printf("\n\t\t\t\t\t%d:\t aaload", i);
			break;

		case 0x33:
			printf("\n\t\t\t\t\t%d:\t baload", i);
			break;

		case 0x34:
			printf("\n\t\t\t\t\t%d:\t caload", i);
			break;

		case 0x35:
			printf("\n\t\t\t\t\t%d:\t saload", i);
			break;

		case 0x36:
			one_byte(&i, "\n\t\t\t\t\t%d:\t istore\t\t", bytecode);
			break;

		case 0x37:
			one_byte(&i, "\n\t\t\t\t\t%d:\t lstore\t\t", bytecode);
			break;

		case 0x38:
			one_byte(&i, "\n\t\t\t\t\t%d:\t fstore\t\t", bytecode);
			break;

		case 0x39:
			one_byte(&i, "\n\t\t\t\t\t%d:\t bstore\t\t", bytecode);
			break;

		case 0x3a:
			one_byte(&i, "\n\t\t\t\t\t%d:\t astore\t\t", bytecode);
			break;

		case 0x3b:
			printf("\n\t\t\t\t\t%d:\t istore_0", i);
			break;

		case 0x3c:
			printf("\n\t\t\t\t\t%d:\t istore_1", i);
			break;

		case 0x3d:
			printf("\n\t\t\t\t\t%d:\t istore_2", i);
			break;

		case 0x3e:
			printf("\n\t\t\t\t\t%d:\t istore_3", i);
			break;

		case 0x3f:
			printf("\n\t\t\t\t\t%d:\t lstore_0", i);
			break;

		case 0x40:
			printf("\n\t\t\t\t\t%d:\t lstore_1", i);
			break;

		case 0x41:
			printf("\n\t\t\t\t\t%d:\t lstore_2", i);
			break;

		case 0x42:
			printf("\n\t\t\t\t\t%d:\t lstore_3", i);
			break;

		case 0x43:
			printf("\n\t\t\t\t\t%d:\t fstore_0", i);
			break;

		case 0x44:
			printf("\n\t\t\t\t\t%d:\t fstore_1", i);
			break;

		case 0x45:
			printf("\n\t\t\t\t\t%d:\t fstore_2", i);
			break;

		case 0x46:
			printf("\n\t\t\t\t\t%d:\t fstore_3", i);
			break;

		case 0x47:
			printf("\n\t\t\t\t\t%d:\t dstore_0", i);
			break;

		case 0x48:
			printf("\n\t\t\t\t\t%d:\t dstore_1", i);
			break;

		case 0x49:
			printf("\n\t\t\t\t\t%d:\t dstore_2", i);
			break;

		case 0x4a:
			printf("\n\t\t\t\t\t%d:\t dstore_3", i);
			break;

		case 0x4b:
			printf("\n\t\t\t\t\t%d:\t astore_0", i);
			break;

		case 0x4c:
			printf("\n\t\t\t\t\t%d:\t astore_1", i);
			break;

		case 0x4d:
			printf("\n\t\t\t\t\t%d:\t astore_2", i);
			break;

		case 0x4e:
			printf("\n\t\t\t\t\t%d:\t astore_3", i);
			break;

		case 0x4f:
			printf("\n\t\t\t\t\t%d:\t iastore", i);
			break;

		case 0x50:
			printf("\n\t\t\t\t\t%d:\t lastore", i);
			break;

		case 0x51:
			printf("\n\t\t\t\t\t%d:\t fastore", i);
			break;

		case 0x52:
			printf("\n\t\t\t\t\t%d:\t dastore", i);
			break;

		case 0x53:
			printf("\n\t\t\t\t\t%d:\t aastore", i);
			break;

		case 0x54:
			printf("\n\t\t\t\t\t%d:\t bastore", i);
			break;

		case 0x55:
			printf("\n\t\t\t\t\t%d:\t castore", i);
			break;

		case 0x56:
			printf("\n\t\t\t\t\t%d:\t sastore", i);
			break;

		case 0x57:
			printf("\n\t\t\t\t\t%d:\t pop", i);
			break;

		case 0x58:
			printf("\n\t\t\t\t\t%d:\t pop2", i);
			break;

		case 0x59:
			printf("\n\t\t\t\t\t%d:\t dup", i);
			break;

		case 0x5a:
			printf("\n\t\t\t\t\t%d:\t dup_x1", i);
			break;

		case 0x5f:
			printf("\n\t\t\t\t\t%d:\t swap", i);
			break;

		case 0x60:
			printf("\n\t\t\t\t\t%d:\t iadd", i);
			break;

		case 0x61:
			printf("\n\t\t\t\t\t%d:\t ladd", i);
			break;

		case 0x62:
			printf("\n\t\t\t\t\t%d:\t fadd", i);
			break;

		case 0x63:
			printf("\n\t\t\t\t\t%d:\t dadd", i);
			break;

		case 0x64:
			printf("\n\t\t\t\t\t%d:\t isub", i);
			break;

		case 0x65:
			printf("\n\t\t\t\t\t%d:\t lsub", i);
			break;

		case 0x66:
			printf("\n\t\t\t\t\t%d:\t fsub", i);
			break;

		case 0x67:
			printf("\n\t\t\t\t\t%d:\t dsub", i);
			break;

		case 0x68:
			printf("\n\t\t\t\t\t%d:\t imul", i);
			break;

		case 0x69:
			printf("\n\t\t\t\t\t%d:\t lmul", i);
			break;

		case 0x6a:
			printf("\n\t\t\t\t\t%d:\t fdiv", i);
			break;

		case 0x6b:
			printf("\n\t\t\t\t\t%d:\t ddiv", i);
			break;

		case 0x6c:
			printf("\n\t\t\t\t\t%d:\t idiv", i);
			break;

		case 0x6d:
			printf("\n\t\t\t\t\t%d:\t ldiv", i);
			break;

		case 0x6e:
			printf("\n\t\t\t\t\t%d:\t fdiv", i);
			break;

		case 0x6f:
			printf("\n\t\t\t\t\t%d:\t ddiv", i);
			break;

		case 0x70:
			printf("\n\t\t\t\t\t%d:\t irem", i);
			break;

		case 0x71:
			printf("\n\t\t\t\t\t%d:\t lrem", i);
			break;

		case 0x72:
			printf("\n\t\t\t\t\t%d:\t frem", i);
			break;

		case 0x73:
			printf("\n\t\t\t\t\t%d:\t drem", i);
			break;

		case 0x74:
			printf("\n\t\t\t\t\t%d:\t ineg", i);
			break;

		case 0x75:
			printf("\n\t\t\t\t\t%d:\t lneg", i);
			break;

		case 0x76:
			printf("\n\t\t\t\t\t%d:\t fneg", i);
			break;

		case 0x77:
			printf("\n\t\t\t\t\t%d:\t dneg", i);
			break;

		case 0x78:
			printf("\n\t\t\t\t\t%d:\t ishl", i);
			break;

		case 0x79:
			printf("\n\t\t\t\t\t%d:\t lshl", i);
			break;

		case 0x7a:
			printf("\n\t\t\t\t\t%d:\t ishr", i);
			break;

		case 0x7b:
			printf("\n\t\t\t\t\t%d:\t lshr", i);
			break;

		case 0x7c:
			printf("\n\t\t\t\t\t%d:\t iushr", i);
			break;

		case 0x7d:
			printf("\n\t\t\t\t\t%d:\t lushr", i);
			break;

		case 0x7e:
			printf("\n\t\t\t\t\t%d:\t iand", i);
			break;

		case 0x7f:
			printf("\n\t\t\t\t\t%d:\t land", i);
			break;

		case 0x80:
			printf("\n\t\t\t\t\t%d:\t ior", i);
			break;

		case 0x81:
			printf("\n\t\t\t\t\t%d:\t lor", i);
			break;

		case 0x82:
			printf("\n\t\t\t\t\t%d:\t ixor", i);
			break;

		case 0x83:
			printf("\n\t\t\t\t\t%d:\t lxor", i);
			break;

		case 0x84:
			two_bytes(&i, "\n\t\t\t\t\t%d:\t iinc\t\t", bytecode);
			break;

		case 0x85:
			printf("\n\t\t\t\t\t%d:\t i2l", i);
			break;

		case 0x86:
			printf("\n\t\t\t\t\t%d:\t i2f", i);
			break;

		case 0x87:
			printf("\n\t\t\t\t\t%d:\t l2d", i);
			break;

		case 0x88:
			printf("\n\t\t\t\t\t%d:\t l2i", i);
			break;

		case 0x89:
			printf("\n\t\t\t\t\t%d:\t l2f", i);
			break;

		case 0x8a:
			printf("\n\t\t\t\t\t%d:\t l2d", i);
			break;

		case 0x8b:
			printf("\n\t\t\t\t\t%d:\t f2i", i);
			break;

		case 0x8c:
			printf("\n\t\t\t\t\t%d:\t f2l", i);
			break;

		case 0x8d:
			printf("\n\t\t\t\t\t%d:\t f2d", i);
			break;

		case 0x8e:
			printf("\n\t\t\t\t\t%d:\t d2i", i);
			break;

		case 0x8f:
			printf("\n\t\t\t\t\t%d:\t d2l", i);
			break;

		case 0x90:
			printf("\n\t\t\t\t\t%d:\t d2f", i);
			break;

		case 0x91:
			printf("\n\t\t\t\t\t%d:\t i2b", i);
			break;

		case 0x92:
			printf("\n\t\t\t\t\t%d:\t i2c", i);
			break;

		case 0x93:
			printf("\n\t\t\t\t\t%d:\t i2s", i);
			break;

		case 0x94:
			printf("\n\t\t\t\t\t%d:\t lcmp\t\t", i);
			break;

		case 0x95:
			printf("\n\t\t\t\t\t%d:\t fcmpl\t\t", i);
			break;

		case 0x96:
			printf("\n\t\t\t\t\t%d:\t fcmpg\t\t", i);
			break;

		case 0x97:
			printf("\n\t\t\t\t\t%d:\t dcmpl\t\t", i);
			break;

		case 0x98:
			printf("\n\t\t\t\t\t%d:\t dcmpg\t\t", i);
			break;

		case 0x99:
			two_bytes(&i, "\n\t\t\t\t\t%d:\t ifeq\t\t", bytecode);
			break;

		case 0x9a:
			two_bytes(&i, "\n\t\t\t\t\t%d:\t ifne\t\t", bytecode);
			break;

		case 0x9b:
			two_bytes(&i, "\n\t\t\t\t\t%d:\t iflt\t\t", bytecode);
			break;

		case 0x9c:
			two_bytes(&i, "\n\t\t\t\t\t%d:\t ifge\t\t", bytecode);
			break;

		case 0x9d:
			two_bytes(&i, "\n\t\t\t\t\t%d:\t ifgt\t\t", bytecode);
			break;

		case 0x9e:
			two_bytes(&i, "\n\t\t\t\t\t%d:\t ifle\t\t", bytecode);
			break;

		case 0x9f:
			two_bytes(&i, "\n\t\t\t\t\t%d:\t if_icmpeq\t", bytecode);
			break;

		case 0xa0:
			two_bytes(&i, "\n\t\t\t\t\t%d:\t if_icmpne\t", bytecode);
			break;

		case 0xa1:
			two_bytes(&i, "\n\t\t\t\t\t%d:\t if_cmplt\t", bytecode);
			break;

		case 0xa2:
			two_bytes(&i, "\n\t\t\t\t\t%d:\t if_icmpge\t", bytecode);
			break;

		case 0xa3:
			two_bytes(&i, "\n\t\t\t\t\t%d:\t if_icmpgt\t", bytecode);
			break;

		case 0xa4:
			two_bytes(&i, "\n\t\t\t\t\t%d:\t if_icmple\t", bytecode);
			break;

		case 0xa5:
			two_bytes(&i, "\n\t\t\t\t\t%d:\t if_acmpeq\t", bytecode);
			break;

		case 0xa6:
			two_bytes(&i, "\n\t\t\t\t\t%d:\t if_acmpne\t", bytecode);
			break;

		case 0xa7:
			two_bytes(&i, "\n\t\t\t\t\t%d:\t goto\t\t", bytecode);
			break;

		case 0xa8:
			two_bytes(&i, "\n\t\t\t\t\t%d:\t jsr\t\t", bytecode);
			break;

		case 0xa9:
			one_byte(&i, "\n\t\t\t\t\t%d:\t ret\t\t", bytecode);
			break;

		case 0xaa:
			four_bytes(&i, "\n\t\t\t\t\t%d:\t ret\t\t", bytecode);
			break;

		case 0xac:
			printf("\n\t\t\t\t\t%d:\t ireturn", i);
			break;

		case 0xad:
			printf("\n\t\t\t\t\t%d:\t lreturn", i);
			break;

		case 0xae:
			printf("\n\t\t\t\t\t%d:\t freturn", i);
			break;

		case 0xaf:
			printf("\n\t\t\t\t\t%d:\t dreturn", i);
			break;

		case 0xb0:
			printf("\n\t\t\t\t\t%d:\t areturn", i);
			break;

		case 0xb1:
			printf("\n\t\t\t\t\t%d:\t return", i);
			break;

		case 0xb2:
			two_bytes(&i, "\n\t\t\t\t\t%d:\t getstatic\t", bytecode);
			break;

		case 0xb3:
			two_bytes(&i, "\n\t\t\t\t\t%d:\t putstatic\t", bytecode);
			break;

		case 0xb4:
			two_bytes(&i, "\n\t\t\t\t\t%d:\t getfield\t", bytecode);
			break;

		case 0xb5:
			two_bytes(&i, "\n\t\t\t\t\t%d:\t putfield\t", bytecode);
			break;

		case 0xb6:
			two_bytes(&i, "\n\t\t\t\t\t%d:\t invokevirtual\t", bytecode);
			break;

		case 0xb7:
			two_bytes(&i, "\n\t\t\t\t\t%d:\t invokespecial\t", bytecode);
			break;

		case 0xb8:
			two_bytes(&i, "\n\t\t\t\t\t%d:\t invokestatic\t", bytecode);
			break;

		case 0xb9:
			two_bytes(&i, "\n\t\t\t\t\t%d:\t invokeinterface\t", bytecode);
			break;

		default:
			printf("\n\t\t\t\t\t%d:\t unknown mnemonic", i);
		}
	}
	printf("\n\n");
}

/*funcao que escreve os mnemonicos mais um byte*/
void one_byte(unsigned int *i, char *mnemonico, unsigned char *bytecode) {
	printf(mnemonico, *i);
	(*i)++;
	printf("%d", bytecode[*i]);
}

/*funcao que escreve os mnemonicos mais dois bytes*/
void two_bytes(unsigned int *i, char *mnemonico, unsigned char *bytecode) {
	printf(mnemonico, *i);
	(*i)++;
	printf("%d", bytecode[*i]);
	(*i)++;
	printf("  %d", bytecode[*i]);
}

/*funcao que escreve os mnemonicos mais quatro bytes*/
void four_bytes(unsigned int *i, char *mnemonico, unsigned char *bytecode) {
	printf(mnemonico, *i);
	(*i)++;
	printf("%d", bytecode[*i]);
	(*i)++;
	printf("  %d", bytecode[*i]);
	(*i)++;
	printf("%d", bytecode[*i]);
	(*i)++;
	printf("  %d", bytecode[*i]);
}
